home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / demos / walker / walker.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  28KB  |  1,105 lines

  1. #include <GL/glut.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <string.h>
  6. #include <dirent.h>
  7. #include <assert.h>
  8.  
  9. #include "walker.h"
  10.  
  11.  
  12.  
  13. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  14. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  15.  
  16. #define CYCLE_SIZE 100
  17. #define CYCLE_STEP 1.0/CYCLE_SIZE
  18. #define OVERSAMPLE 10
  19.  
  20. #define MAX_CPOINTS 34   /* 2 end point ones and 10 in the middle */
  21.  
  22. #define MAX_CSETNAMELEN 25
  23.  
  24. #define NUM_JOINTS 5
  25.  
  26. #define CSET_EXT ".cset"
  27. #define CSET_EXTLEN 5
  28.  
  29. #include "walkviewer.h"
  30.  
  31.  
  32. typedef enum { CMENU_QUIT, CMENU_CURVE, CMENU_HORIZ, CMENU_RESET,
  33.                CMENU_WALK, CMENU_DONEEDIT, CMENU_SAVE, CMENU_LOAD,
  34.            CMENU_MIRROR
  35.               } CurveMenuChoices;
  36.  
  37. typedef enum { WIRECUBE, SOLIDCUBE, CYLINDER1, CYLINDER2 } ModelTypes;
  38.  
  39. int GuyModel = SOLIDCUBE;
  40.  
  41. /***************************************************************/
  42. /*************************** GLOBALS ***************************/
  43. /***************************************************************/
  44.  
  45. GLuint HorizontalList, AxesList,     /* Display lists */
  46.        CurveLists, ControlPtsLists;  /* Firsts of groups of display lists */
  47.  
  48. int CurveAsPoints   =  0,    /* Display curve as points? */
  49.     DrawHorizontals =  0,    /* Draw horizontal lines?   */
  50.     EditingCurve    = -1;    /* Editing what curve, -1 means none */
  51.  
  52. int CurveWindow,   /* Glut window id's to two top level windows */
  53.     GuyWindow;
  54.  
  55. int MirrorLegs = 0;
  56.  
  57. int CurveMenu     = -1,
  58.     CurveEditMenu = -1,
  59.     StepSizeMenu  = -1,
  60.     LoadMenu      = -1,
  61.     SaveMenu      = -1;
  62.  
  63. char *CSetNames[MAX_CSETNAMELEN];
  64.  
  65. int CurrentCurve = -1;  /* Curve loaded, index to CSetNames */
  66.  
  67. GLfloat Walk_cycle[2][NUM_JOINTS][CYCLE_SIZE];  /* array of computed angles */
  68.  
  69. int Step = CYCLE_SIZE/2;  /* Position in cycle, start in middle */
  70.  
  71. float fStep = CYCLE_SIZE/2;   /* floating point for non-integer steping */
  72. float IncStep = 1.0;
  73.  
  74. typedef struct ControlPts {
  75.   int numpoints;
  76.   float xcoords[MAX_CPOINTS];
  77.   float angles[MAX_CPOINTS];
  78. } tControlPts;
  79.  
  80. tControlPts RotCurve[NUM_JOINTS];   /* series of cntrl points for ea joint */
  81.  
  82. int Walking         = 0,     /* Guy is walking? */
  83.     ViewPerspective = 1,     /* Perspective or orthographic views */
  84.     DrawAxes        = 0;     /* Draw axes for alignment */
  85.  
  86. int CurveWWidth,             /* Dimensions of curve window */
  87.     CurveWHeight;  
  88.  
  89. int CurveDownBtn = -1,               /* mouse stuff, for editing curves */
  90.     WasWalking,
  91.     CurvePickedPoint = -1,
  92.     CurveLastX,
  93.     CurveLastY;
  94.  
  95. int CurveWindowVisible = 1;
  96.  
  97.  
  98.   /* prototypes */
  99. void RedisplayBoth(void);
  100. void IncrementStep(void);
  101. void CurveCPointDrag(void);
  102. void CurveHandleMenu(int value);
  103. void StopWalking(void);
  104. void CurveHandleEditMenu(int curve);
  105. void ComputeCSetAndMakeLists(void);
  106. int MakeLoadAndSaveMenus(void);
  107. void CurveMenuInit(void);
  108. void SetWindowTitles(char *csetname);
  109.  
  110. /***************************************************************/
  111. /**************************** BEZIER ***************************/
  112. /***************************************************************/
  113.  
  114.   /* Matrix times a vector  dest = m*v */
  115. void MultMV(float m[3][4], float v[4], float dest[3])
  116. {
  117.   int i, j;
  118.  
  119.   for (i = 0; i < 3; i++) {
  120.     dest[i] = 0;
  121.     for (j = 0; j < 4; j++)
  122.       dest[i] += m[i][j] * v[j];
  123.   }
  124. }
  125.  
  126.   /* Matrix multiplication, dest = m1*m2 */
  127. void MultM(float m1[3][4], float m2[4][4], float dest[3][4])
  128. {
  129.   int i, j, k;
  130.  
  131.   for (i = 0; i < 3; i++)
  132.     for (j = 0; j < 4; j++) {
  133.       dest[i][j] = 0;
  134.       for (k = 0; k < 4; k++)
  135.       dest[i][j] += (m1[i][k] * m2[k][j]);
  136.     }
  137. }
  138.  
  139. void ComputeCurve(int joint)
  140. {
  141.   float prod[3][4], tm[4], pos[3];
  142.   float t = 0, tinc = (float)CYCLE_STEP/OVERSAMPLE;
  143.   int ctlpoint, i;
  144.   float BBasis[4][4] = {{-1, 3, -3, 1}, {3, -6, 3, 0},
  145.                         {-3, 3,  0, 0}, {1,  0, 0, 0}};
  146.   int lastindex, newindex;
  147.  
  148.   float pointset[3][4];
  149.   for (i = 0; i < 4; i++)   /* z's are always zero, only 2-d */
  150.     pointset[2][i] = 0; 
  151.  
  152.   lastindex = -1;
  153.   for(ctlpoint = 0; ctlpoint < RotCurve[joint].numpoints; ctlpoint += 3) {
  154.     t = 0;
  155.     for (i = 0; i < 4; i++)
  156.       pointset[0][i] = RotCurve[joint].xcoords[ctlpoint + i];
  157.     for (i = 0; i < 4; i++)
  158.       pointset[1][i] = RotCurve[joint].angles[ctlpoint + i];
  159.  
  160.     MultM(pointset, BBasis, prod);
  161.  
  162.     while (t <= 1) {
  163.       tm[0] = t*t*t;
  164.       tm[1] = t*t;
  165.       tm[2] = t;
  166.       tm[3] = 1;
  167.       MultMV(prod, tm, pos);
  168.       newindex = (int)(pos[0]*(CYCLE_SIZE-1));
  169.       if ((int)(newindex > lastindex))  {  /* go at least one */
  170.     Walk_cycle[0][joint][newindex] = pos[1];
  171.     lastindex++;
  172.       } 
  173.       t += tinc;
  174.     }
  175.   }
  176.  
  177.   for (i = 0; i < CYCLE_SIZE; i++) {      /* copy to other leg, out-o-phase */
  178.     if (MirrorLegs)
  179.       Walk_cycle[1][joint][i] =
  180.         Walk_cycle[0][joint][i];
  181.     else
  182.       Walk_cycle[1][joint][i] =
  183.         Walk_cycle[0][joint][(i+(CYCLE_SIZE/2))%CYCLE_SIZE];
  184.   }
  185. }
  186.  
  187. /***************************************************************/
  188. /************************* CURVE I/O ***************************/
  189. /***************************************************************/
  190.  
  191. void FlatCSet(void)
  192. {
  193.   int joint;
  194.  
  195.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  196.     RotCurve[joint].numpoints = 4;
  197.     RotCurve[joint].xcoords[0] = 0.0;
  198.     RotCurve[joint].angles[0]  = 0.0;
  199.     RotCurve[joint].xcoords[1] = 0.2;
  200.     RotCurve[joint].angles[1]  = 0.0;
  201.     RotCurve[joint].xcoords[2] = 0.8;
  202.     RotCurve[joint].angles[2]  = 0.0;
  203.     RotCurve[joint].xcoords[3] = 1.0;
  204.     RotCurve[joint].angles[3]  = 0.0;
  205.   }
  206. }
  207.  
  208. int ReadCSetFromFile(char *filename)
  209. {
  210.   FILE *infile = fopen(filename, "r");
  211.   int numjoints, numpoints, joint, point, mirrorlegs;
  212.   float value;
  213.  
  214.   if (infile == NULL)
  215.     goto abort;
  216.   
  217.   if (!fscanf(infile, " %d", &numjoints) || numjoints != NUM_JOINTS)
  218.     goto abort;
  219.  
  220.   if (!fscanf(infile, " %d", &mirrorlegs) || (mirrorlegs != 0 &&
  221.                                               mirrorlegs != 1))
  222.     goto abort;
  223.  
  224.   MirrorLegs = mirrorlegs;
  225.  
  226.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  227.     if (!fscanf(infile, " %d", &numpoints) || numpoints < 4 || 
  228.                                               numpoints > MAX_CPOINTS)
  229.       goto abort;
  230.     RotCurve[joint].numpoints = numpoints;
  231.     for (point = 0; point < numpoints; point++) {
  232.       if (!fscanf(infile, " %f", &value))
  233.     goto abort;
  234.       RotCurve[joint].xcoords[point] = value;
  235.     }
  236.     for (point = 0; point < numpoints; point++) {
  237.       if (!fscanf(infile, " %f", &value))
  238.     goto abort;
  239.       RotCurve[joint].angles[point] = value;
  240.     }
  241.   }
  242.  
  243.   fclose(infile);
  244.   return 0;
  245.  
  246.   abort:
  247.     fclose(infile);
  248.     fprintf(stderr, "Something went wrong while reading file %s\n", filename);
  249.     FlatCSet();
  250.     return -1;
  251. }
  252.  
  253. void WriteCSetToFile(char *filename)
  254. {
  255.   FILE *outfile = fopen(filename, "w+");
  256.   int joint, point;
  257.  
  258.   if (outfile == NULL) {
  259.     fprintf(stderr, "Error: could not create file %s\n", filename);
  260.     return;
  261.   }
  262.  
  263.   fprintf(outfile, "%d\n", NUM_JOINTS);
  264.  
  265.   fprintf(outfile, "%d\n", MirrorLegs);
  266.  
  267.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  268.  
  269.     fprintf(outfile, "%d\n", RotCurve[joint].numpoints);
  270.  
  271.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  272.       fprintf(outfile, "%f ", RotCurve[joint].xcoords[point]);
  273.     }
  274.     fprintf(outfile, "\n");
  275.  
  276.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  277.       fprintf(outfile, "%f ", RotCurve[joint].angles[point]);
  278.     }
  279.     fprintf(outfile, "\n");
  280.   }
  281.  
  282.   fclose(outfile);
  283. }
  284.  
  285. void HandleLoadMenu(int cset)
  286. {
  287.   char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
  288.  
  289.   if (cset == -1) {
  290.     MakeLoadAndSaveMenus();
  291.     CurveMenuInit();
  292.   } else {
  293.     (void)strcpy(filename, CSetNames[cset]);
  294.     (void)strcat(filename, CSET_EXT);
  295.     if (ReadCSetFromFile(filename) == 0) {
  296.       glutSetMenu(SaveMenu);
  297.       glutChangeToMenuEntry(1, CSetNames[cset], cset);
  298.       ComputeCSetAndMakeLists();
  299.       SetWindowTitles(CSetNames[cset]);
  300.       RedisplayBoth();
  301.     }
  302.   }
  303. }
  304.  
  305. void HandleSaveMenu(int cset)
  306. {
  307.   char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
  308.  
  309.   (void)strcpy(filename, CSetNames[cset]);
  310.   (void)strcat(filename, CSET_EXT);
  311.   WriteCSetToFile(filename);
  312.   ComputeCSetAndMakeLists();
  313.   RedisplayBoth();
  314. }
  315.  
  316. int MakeLoadAndSaveMenus(void)
  317. {
  318.   DIR *dirp = opendir(".");
  319.   struct dirent *direntp;
  320.   int csetnum = 0;
  321.   char *newcsetname;
  322.  
  323.   if (LoadMenu != -1)
  324.     glutDestroyMenu(LoadMenu);
  325.   if (SaveMenu != -1)
  326.     glutDestroyMenu(SaveMenu);
  327.  
  328.   SaveMenu = glutCreateMenu(HandleSaveMenu);
  329.   LoadMenu = glutCreateMenu(HandleLoadMenu);
  330.  
  331.   if (dirp == NULL) {
  332.     fprintf(stderr, "Error opening current dir in MakeLoadAndSaveMenus\n");
  333.     return(0);
  334.   }
  335.  
  336.   while ((direntp = readdir(dirp)) != NULL) {
  337.     char *ext = direntp->d_name + (strlen(direntp->d_name) - CSET_EXTLEN);
  338.     if (!strcmp(ext, CSET_EXT)) {
  339.       newcsetname = malloc(strlen(direntp->d_name) - CSET_EXTLEN + 1);
  340.       strncpy(newcsetname, direntp->d_name,
  341.           strlen(direntp->d_name) - CSET_EXTLEN);
  342.       newcsetname[strlen(direntp->d_name) - CSET_EXTLEN] = 0;
  343.       CSetNames[csetnum] = newcsetname;
  344.       glutAddMenuEntry(newcsetname, csetnum++);
  345.     }
  346.   }
  347.   closedir(dirp);
  348.   glutSetMenu(LoadMenu);
  349.   glutAddMenuEntry("-> Rescan Directory <-", -1);
  350.   glutSetMenu(SaveMenu);
  351.   CSetNames[csetnum] = "NewCurve0";
  352.   glutAddMenuEntry("NewCurve0", csetnum++);
  353.   CSetNames[csetnum] = "NewCurve1";
  354.   glutAddMenuEntry("NewCurve1", csetnum++);
  355.   CSetNames[csetnum] = "NewCurve2";
  356.   glutAddMenuEntry("NewCurve2", csetnum++);
  357.  
  358.   return (csetnum - 2);  /* just indicate curves in Load menu */
  359. }
  360.  
  361.  
  362. /***************************************************************/
  363. /********************* DISPLAY LISTS ***************************/
  364. /***************************************************************/
  365.  
  366.  
  367. void MakeCurveList(int joint)
  368. {
  369.   int i;
  370.  
  371.   glNewList(CurveLists+joint, GL_COMPILE);
  372.   glColor3f(1, 1, 1);
  373.   for (i = 0; i < CYCLE_SIZE; i++) {
  374.     glVertex3f((GLfloat)i/CYCLE_SIZE, Walk_cycle[0][joint][i]/180, 0);
  375.   }
  376.   glEndList();
  377. }
  378.  
  379. void MakeCPointList(int joint)
  380. {
  381.   int point;
  382.  
  383.   glNewList(ControlPtsLists+joint, GL_COMPILE);
  384.  
  385.     glColor3f(0, 0.4, 0);
  386.     glBegin(GL_LINE_STRIP);
  387.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  388.       if (!((point-2) % 3)) {
  389.         glEnd();
  390.         glBegin(GL_LINE_STRIP);
  391.       }
  392.       glVertex3f(RotCurve[joint].xcoords[point],
  393.              (RotCurve[joint].angles[point])/180.0, 0.0);
  394.     }
  395.     glEnd();
  396.  
  397.     glBegin(GL_POINTS);
  398.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  399.       if (point % 3)
  400.         glColor3f(0, 0.7, 0);
  401.       else
  402.         glColor3f(0.7, 0.0, 0);
  403.       glVertex3f(RotCurve[joint].xcoords[point],
  404.              (RotCurve[joint].angles[point])/180, 0);
  405.     }
  406.     glEnd();
  407.  
  408.   glEndList();
  409. }
  410.  
  411. void MakeJointLists(int joint)
  412. {
  413.   MakeCurveList(joint);
  414.   MakeCPointList(joint);
  415. }
  416.  
  417.  
  418. void ComputeCSetAndMakeLists(void)
  419. {
  420.   int joint;
  421.  
  422.   for(joint = 0; joint < NUM_JOINTS; joint++) {
  423.     ComputeCurve(joint);
  424.     MakeJointLists(joint);
  425.   }
  426. }
  427.  
  428. void MakeLists(void)
  429. {
  430.   HorizontalList = glGenLists(1);
  431.   glNewList(HorizontalList, GL_COMPILE);
  432.   {
  433.     float line1 = 25.0/180,
  434.           line2 = 35.0/180,
  435.           line3 = 45.0/180;
  436.     glColor3f(0, 0, 0.7);
  437.     glPushAttrib(GL_ENABLE_BIT);
  438.     glEnable(GL_LINE_STIPPLE);
  439.     glBegin(GL_LINES);
  440.       glVertex3f(0, 0, 0.5);
  441.       glVertex3f(1, 0, 0.5);
  442.       glVertex3f(0, line1, 0.5);  glVertex3f(1, line1, 0.5);
  443.       glVertex3f(0, -line1, 0.5); glVertex3f(1, -line1, 0.5);
  444.       glVertex3f(0, line2, 0.5);  glVertex3f(1, line2, 0.5);
  445.       glVertex3f(0, -line2, 0.5); glVertex3f(1, -line2, 0.5);
  446.       glVertex3f(0, line3, 0.5);  glVertex3f(1, line3, 0.5);
  447.       glVertex3f(0, -line3, 0.5); glVertex3f(1, -line3, 0.5);
  448.     glEnd();
  449.     glPopAttrib();
  450.   }
  451.   glEndList();
  452.  
  453.  
  454.   CurveLists = glGenLists(NUM_JOINTS);
  455.   assert(CurveLists != 0);
  456.  
  457.   ControlPtsLists = glGenLists(NUM_JOINTS);
  458.   assert(ControlPtsLists != 0);
  459.  
  460.   ComputeCSetAndMakeLists();
  461. }
  462.  
  463. /***************************************************************/
  464. /********************* curve WINDOW ****************************/
  465. /***************************************************************/
  466.  
  467. void CurveReshape(int w, int h)
  468. {
  469.   glViewport(0,0,w,h);
  470.   CurveWWidth = w; 
  471.   CurveWHeight = h;
  472.   glFlush();
  473. }
  474.  
  475. void CurveDisplay(void)
  476. {
  477.   int joint, otherlegstep;
  478.  
  479.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  480.  
  481.   glPushMatrix();
  482.   glTranslatef(0, 0.5, 0);
  483.  
  484.   for (joint = NUM_JOINTS-1; joint >= 0; joint--) {
  485.  
  486.     if (DrawHorizontals) 
  487.       glCallList(HorizontalList);
  488.  
  489.     (CurveAsPoints) ?
  490.     glBegin(GL_POINTS) :
  491.     glBegin(GL_LINE_STRIP);
  492.       glCallList(CurveLists+joint);
  493.     glEnd();
  494.  
  495.     if (joint == EditingCurve) { 
  496.       glPointSize(5.0);
  497.       glCallList(ControlPtsLists+EditingCurve);
  498.       glPointSize(1.0);
  499.     }
  500.   glTranslatef(0, 1, 0);
  501.   }
  502.  
  503.   glPopMatrix();
  504.  
  505.   otherlegstep = (Step+50) % CYCLE_SIZE;
  506.     /* draw vertical line */
  507.   glColor3f(1, 1, 1);
  508.   glBegin(GL_LINES);
  509.     glVertex3f((GLfloat)Step/CYCLE_SIZE, 0, 0);
  510.     glVertex3f((GLfloat)Step/CYCLE_SIZE, NUM_JOINTS, 0);
  511.     if (!MirrorLegs) {
  512.       glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, 0, 0);
  513.       glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, NUM_JOINTS, 0);
  514.     }
  515.   glEnd();
  516.  
  517.   glFlush();
  518.   glutSwapBuffers();
  519. }
  520.  
  521.  
  522. void CurveGLInit(void)
  523. {
  524.   glMatrixMode(GL_PROJECTION);
  525.   glLoadIdentity();
  526.   glOrtho(0,1,0,NUM_JOINTS,1,-1);
  527.  
  528.   glMatrixMode(GL_MODELVIEW);
  529.   glLoadIdentity();
  530.  
  531.   glLineStipple(1, 0x00FF);
  532.  
  533.   glEnable(GL_DEPTH_TEST);
  534.   glDepthFunc(GL_LEQUAL);
  535.  
  536.  
  537.   glFlush();
  538.  
  539.  
  540.  
  541.  
  542. void CurveHandleButton(int button, int state, int x, int y)
  543. {
  544.   if (button == GLUT_RIGHT_BUTTON )
  545.     return;
  546.  
  547.   if (state == GLUT_DOWN && CurveDownBtn == -1) {
  548.     if (button == GLUT_MIDDLE_BUTTON)
  549.       CurveHandleMenu(CMENU_WALK);
  550.     else
  551.       fStep = Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE);
  552.       
  553.     CurveDownBtn = button;
  554.  
  555.     WasWalking = Walking;
  556.     StopWalking();
  557.     RedisplayBoth();
  558.   } else if (button == CurveDownBtn) {
  559.     CurveDownBtn = -1;
  560.     if (WasWalking) {
  561.       Walking = 1;
  562.       agvSetAllowIdle(0);
  563.       glutIdleFunc(IncrementStep);    
  564.     }
  565.   }
  566. }
  567.  
  568. float CurveEditConstrain(float fx)
  569. {
  570.   if (CurvePickedPoint == 0)
  571.     fx = 0;
  572.   else if (CurvePickedPoint == RotCurve[EditingCurve].numpoints-1)
  573.     fx = 1;
  574.   else if (!(CurvePickedPoint % 3)) {  /* is a pivot */
  575.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
  576.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);   
  577.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-3]);
  578.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+3]);       
  579.   } else if (!((CurvePickedPoint - 1) % 3)) {   /* is right slope */
  580.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
  581.   } else {
  582.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);
  583.   } 
  584.   return fx;
  585. }
  586.  
  587. void RemovePoint(int pt)
  588. {
  589.   int i;
  590.  
  591.   for (i = pt - 1; i < RotCurve[EditingCurve].numpoints; i++) {
  592.     RotCurve[EditingCurve].xcoords[i] = RotCurve[EditingCurve].xcoords[i+3];
  593.     RotCurve[EditingCurve].angles[i]  = RotCurve[EditingCurve].angles[i+3];
  594.   }
  595.   RotCurve[EditingCurve].numpoints -= 3;
  596. }
  597.  
  598. void AddPoint(float fx)
  599. {
  600.   int i, j;
  601.  
  602.   if (fx < 0.05 || fx > 0.95 || RotCurve[EditingCurve].numpoints + 3 >=
  603.                                 MAX_CPOINTS)
  604.     return;
  605.  
  606.   for (i = 3; i < RotCurve[EditingCurve].numpoints; i += 3) {
  607.     if (fx < RotCurve[EditingCurve].xcoords[i]) {
  608.       for (j = RotCurve[EditingCurve].numpoints + 2; j > i + 1; j--) { 
  609.         RotCurve[EditingCurve].xcoords[j] =
  610.                 RotCurve[EditingCurve].xcoords[j-3];
  611.         RotCurve[EditingCurve].angles[j] =
  612.                 RotCurve[EditingCurve].angles[j-3];
  613.       }
  614.     RotCurve[EditingCurve].xcoords[i]   = fx;
  615.     RotCurve[EditingCurve].angles[i]    =
  616.       Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)];
  617.     RotCurve[EditingCurve].xcoords[i-1] = fx - 0.05;
  618.     RotCurve[EditingCurve].angles[i-1]  =
  619.       Walk_cycle[0][EditingCurve][(int)((fx-0.05)*CYCLE_SIZE)];
  620.     RotCurve[EditingCurve].xcoords[i+1] = fx + 0.05;
  621.     RotCurve[EditingCurve].angles[i+1]  = 
  622.       Walk_cycle[0][EditingCurve][(int)((fx+0.05)*CYCLE_SIZE)];
  623.     RotCurve[EditingCurve].numpoints += 3;
  624.     break;
  625.     }
  626.   }  
  627. }
  628.  
  629.  
  630. void CurveEditHandleButton(int button, int state, int x, int y)
  631. {
  632.   float fx, fy;
  633.   int point;
  634.  
  635.   fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  636.        ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  637.   fx = (float)x/CurveWWidth;
  638.   
  639.   if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON &&
  640.                             CurveDownBtn == -1) {
  641.     CurvePickedPoint = -1;
  642.     
  643.     for (point = 0; point < RotCurve[EditingCurve].numpoints; point++) {
  644.       if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
  645.       fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
  646.     CurvePickedPoint = point;
  647.     CurveLastX = x;
  648.     CurveLastY = y;
  649.     glutIdleFunc(CurveCPointDrag);
  650.     break;
  651.       }
  652.     }
  653.    if (CurvePickedPoint == -1)
  654.      CurveHandleButton(button, state, x, y);
  655.     CurveDownBtn = button;
  656.  
  657.  
  658.   } else if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON &&
  659.                                    CurveDownBtn == -1) {
  660.  
  661.     for (point = 3; point < RotCurve[EditingCurve].numpoints - 1; point += 3) {
  662.       if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
  663.       fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
  664.     break;
  665.       }
  666.     }
  667.     if (point >= 3 && point < RotCurve[EditingCurve].numpoints - 1)
  668.       RemovePoint(point);
  669.     else if (fabs(Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)] - fy) < 4)
  670.       AddPoint(fx);
  671.     ComputeCurve(EditingCurve);
  672.     MakeJointLists(EditingCurve);    
  673.     RedisplayBoth();
  674.  
  675.   } else if (button == GLUT_LEFT_BUTTON && button == CurveDownBtn) {
  676.  
  677.     y = MAX(y, 0); y = MIN(y, CurveWHeight);
  678.     x = MAX(x, 0); x = MIN(x, CurveWWidth);
  679.     fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  680.          ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  681.     fx = (float)x/CurveWWidth;
  682.     CurveDownBtn = -1;
  683.     if (CurvePickedPoint != -1) {
  684.       fx = CurveEditConstrain(fx);
  685.       RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
  686.       RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;        
  687.       ComputeCurve(EditingCurve);
  688.       MakeJointLists(EditingCurve);
  689.       glutIdleFunc(NULL);
  690.       RedisplayBoth();
  691.     }
  692.   }
  693. }  
  694.  
  695.  
  696. void CurveHandleMotion(int x, int y)
  697. {
  698.   if (CurvePickedPoint == -1) { 
  699.     
  700.     if (CurveDownBtn == GLUT_LEFT_BUTTON || CurveDownBtn ==
  701.                                             GLUT_MIDDLE_BUTTON) {
  702.       Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE)
  703.     % CYCLE_SIZE;
  704.       if (Step < 0)
  705.     Step = CYCLE_SIZE + Step;
  706.       fStep = Step;
  707.  
  708.     RedisplayBoth();
  709.     }
  710.   } else {
  711.     y = MAX(y, 0); y = MIN(y, CurveWHeight);
  712.     x = MAX(x, 0); x = MIN(x, CurveWWidth);
  713.     CurveLastX = x;
  714.     CurveLastY = y;
  715.   }
  716. }
  717.  
  718. void CurveCPointDrag(void)
  719. {
  720.   float fx, fy;
  721.  
  722.   if (CurveDownBtn == GLUT_LEFT_BUTTON && CurvePickedPoint != -1) {
  723.     fy = -(((float)CurveLastY -
  724.            ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  725.           ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  726.     fx = (float)CurveLastX/CurveWWidth;
  727.  
  728.     fx = CurveEditConstrain(fx);
  729.     RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
  730.     RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;        
  731.     ComputeCurve(EditingCurve);
  732.     MakeJointLists(EditingCurve);
  733.     RedisplayBoth();
  734.   }
  735. }
  736.  
  737. void CurveHandleKeys(unsigned char key, int x, int y)
  738. {
  739.   if (key > '0' && key < '9')
  740.     CurveHandleEditMenu((key-'0')-1);
  741.   else if (key == 'd')
  742.     CurveHandleMenu(CMENU_DONEEDIT);
  743.   else {
  744.     switch(key) {
  745.       case 'f':
  746.       case ' ': Step++;
  747.                 StopWalking(); break;
  748.       case 'F': Step += 5;
  749.                 StopWalking(); break;
  750.       case 'b': Step--;
  751.                 StopWalking(); break;
  752.       case 'B': Step -= 5; 
  753.                 StopWalking(); break;
  754.     }
  755.     Step %= CYCLE_SIZE;
  756.     if (Step < 0)
  757.       Step = CYCLE_SIZE + Step;
  758.     fStep = Step;
  759.     RedisplayBoth();
  760.   }
  761. }
  762.  
  763. void CurveHandleEditMenu(int curve)
  764. {
  765.   if (curve >= NUM_JOINTS)
  766.     return;
  767.   if (EditingCurve == -1) {
  768.     WasWalking = Walking;
  769.     Walking = 0;
  770.     agvSetAllowIdle(0);   /* don't allow spinning, just slows us down */
  771.     glutIdleFunc(NULL);
  772.     glutMouseFunc(CurveEditHandleButton);
  773.   }
  774.   EditingCurve = curve;
  775.   glutPostRedisplay();
  776. }
  777.  
  778. void CurveHandleSZMenu(int size)
  779. {
  780.   IncStep = (float)size/100;
  781. }
  782.  
  783. void CurveHandleMenu(int value)
  784. {
  785.   switch (value) {
  786.     case CMENU_QUIT:
  787.       exit(0);
  788.       break;
  789.     case CMENU_CURVE:
  790.       CurveAsPoints = !CurveAsPoints;
  791.       glutPostRedisplay();
  792.       break;
  793.     case CMENU_HORIZ:
  794.       DrawHorizontals = !DrawHorizontals;
  795.       glutPostRedisplay();
  796.       break;
  797.     case CMENU_WALK:
  798.       if (EditingCurve != -1)
  799.     break;
  800.       Walking = !Walking;
  801.       if (Walking) {
  802.         agvSetAllowIdle(0);
  803.     glutIdleFunc(IncrementStep);    
  804.       } else {
  805.         agvSetAllowIdle(1);
  806.       }
  807.       break;
  808.     case CMENU_DONEEDIT:
  809.       glutMouseFunc(CurveHandleButton);
  810.       EditingCurve = -1;
  811.       CurvePickedPoint = -1;
  812.       Walking = WasWalking;
  813.       if (Walking)
  814.     glutIdleFunc(IncrementStep);
  815.       else
  816.         agvSetAllowIdle(1);
  817.       glutPostRedisplay();
  818.       break;
  819.     case CMENU_RESET:
  820.       FlatCSet();
  821.       ComputeCSetAndMakeLists();
  822.       glutPostRedisplay();
  823.       break;
  824.     case CMENU_MIRROR:
  825.       MirrorLegs = !MirrorLegs;
  826.       ComputeCSetAndMakeLists();
  827.       glutPostRedisplay();      
  828.     }
  829. }
  830.  
  831. void CurveMenuInit(void)
  832. {
  833.   int i;
  834.   char label[3];
  835.  
  836.   if (CurveEditMenu != -1) {
  837.     glutDestroyMenu(CurveEditMenu);
  838.     glutDestroyMenu(CurveMenu);
  839.     glutDestroyMenu(StepSizeMenu);
  840.   }
  841.  
  842.   CurveEditMenu = glutCreateMenu(CurveHandleEditMenu);
  843.   for (i = 0; i < NUM_JOINTS; i++) {
  844.     sprintf(label, " %d ", i+1);
  845.     glutAddMenuEntry(label, i);
  846.   }
  847.   StepSizeMenu = glutCreateMenu(CurveHandleSZMenu);
  848.   glutAddMenuEntry("0.25", 25);
  849.   glutAddMenuEntry("0.5",  50);
  850.   glutAddMenuEntry("1.0", 100);
  851.   glutAddMenuEntry("2.0", 200);
  852.   glutAddMenuEntry("3.0", 300);
  853.   glutAddMenuEntry("5.0", 500);
  854.   CurveMenu = glutCreateMenu(CurveHandleMenu);
  855.   glutAddSubMenu("Load Curve Set", LoadMenu);
  856.   glutAddSubMenu("Save As Curve Set", SaveMenu);
  857.   glutAddSubMenu("Edit Curve", CurveEditMenu);
  858.   glutAddMenuEntry("Done Editing", CMENU_DONEEDIT);
  859.   glutAddMenuEntry("Flatten Curve Set", CMENU_RESET);
  860.   glutAddMenuEntry("Toggle mirrored", CMENU_MIRROR);
  861.   glutAddSubMenu("Step size", StepSizeMenu);
  862.   glutAddMenuEntry("Toggle dotted", CMENU_CURVE);
  863.   glutAddMenuEntry("Toggle horizontals", CMENU_HORIZ);
  864.   glutAddMenuEntry("Toggle walking", CMENU_WALK);
  865.   glutAddMenuEntry("Quit", CMENU_QUIT);
  866.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  867. }
  868.  
  869. void CurveVisible(int v)
  870. {
  871.   if (v == GLUT_VISIBLE)
  872.     CurveWindowVisible = 1;
  873.   else 
  874.     CurveWindowVisible = 0;
  875. }
  876.  
  877. /***************************************************************/
  878. /*********************** GUY WINDOW ****************************/
  879. /***************************************************************/
  880.  
  881. void GuyDisplay(void)
  882. {
  883.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  884.   glFlush();
  885.  
  886.   glLoadIdentity();
  887.  
  888.   agvViewTransform();
  889.  
  890.   if (DrawAxes)
  891.     glCallList(AxesList);
  892.  
  893.   switch(GuyModel) {
  894.     case WIRECUBE:   DrawTheGuy_WC();  break;
  895.     case SOLIDCUBE:  DrawTheGuy_SC();  break;
  896.     case CYLINDER1:  DrawTheGuy_SL();  break;
  897.     case CYLINDER2:  DrawTheGuy_SL2(); break;
  898.   }
  899.  
  900.   glutSwapBuffers();
  901.   glFlush();
  902. }
  903.  
  904. void GuyReshape(int w, int h)
  905. {
  906.   glViewport(0,0,w,h);
  907.   glMatrixMode(GL_PROJECTION);
  908.   glLoadIdentity();
  909.   if (ViewPerspective)
  910.     gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
  911.   else
  912.     glOrtho(-1.2, 1.2, -1.2, 1.2, 0.1, 100);
  913.   glMatrixMode(GL_MODELVIEW);
  914.   glFlush();
  915. }
  916.  
  917.  
  918. void GuyGLInit(void)
  919. {
  920.   GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
  921.   GLfloat light_position[] = { 0.3, 0.5, 0.8, 0.0 };
  922.   GLfloat lm_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
  923.   
  924.   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  925.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  926.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lm_ambient);
  927.   
  928.   glEnable(GL_LIGHTING);
  929.   glEnable(GL_LIGHT0);
  930.   glDepthFunc(GL_LESS);
  931.   glEnable(GL_DEPTH_TEST);
  932.   glEnable(GL_NORMALIZE);
  933.   glShadeModel(GL_SMOOTH);
  934.   /* Cylinder stuff */
  935.   StoreTheGuy_SL();
  936.   StoreTheGuy_SL2();
  937. }
  938.  
  939. void GuyHandleKeys(unsigned char key, int x, int y)
  940. {
  941.   switch(key) {
  942.     case 'f':
  943.     case ' ': Step++;
  944.               StopWalking(); break;
  945.     case 'F': Step += 5;
  946.               StopWalking(); break;
  947.     case 'b': Step--;
  948.               StopWalking(); break;
  949.     case 'B': Step -= 5; 
  950.               StopWalking(); break;
  951.   }
  952.   Step %= CYCLE_SIZE;
  953.   if (Step < 0)
  954.     Step = CYCLE_SIZE + Step;
  955.   agvHandleKeys(key, x, y);
  956.   RedisplayBoth();
  957. }
  958.  
  959. typedef enum { GMENU_QUIT, GMENU_CURVE, GMENU_HORIZ,
  960.                GMENU_AXES, GMENU_PERSP } GuyMenuChoices;
  961.  
  962.  
  963. void GuyModelHandleMenu(int model)
  964. {
  965.   GuyModel = model;
  966.   if (model == WIRECUBE)
  967.     glDisable(GL_LIGHTING);
  968.   else
  969.     glEnable(GL_LIGHTING);
  970.   glutPostRedisplay();
  971. }
  972.  
  973. void GuyHandleMenu(int value)
  974. {
  975.   switch (value) {
  976.     case GMENU_QUIT:
  977.       exit(0);
  978.       break;
  979.     case GMENU_AXES:
  980.       DrawAxes = !DrawAxes;
  981.       glutPostRedisplay();
  982.       break;
  983.     case GMENU_PERSP:
  984.       ViewPerspective = !ViewPerspective;
  985.       GuyReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  986.       glutPostRedisplay();
  987.       break;
  988.   }
  989. }
  990.  
  991. void GuyMenuInit(void)
  992. {
  993.   int sub2, sub1 = glutCreateMenu(agvSwitchMoveMode);
  994.   glutAddMenuEntry("Flying move",  FLYING);
  995.   glutAddMenuEntry("Polar move",   POLAR);
  996.   sub2 = glutCreateMenu(GuyModelHandleMenu);
  997.   glutAddMenuEntry("Wire cubes",  WIRECUBE);
  998.   glutAddMenuEntry("Solid cubes", SOLIDCUBE);
  999.   glutAddMenuEntry("Cylinder 1",  CYLINDER1);
  1000.   glutAddMenuEntry("Cylinder 2",  CYLINDER2);
  1001.   glutCreateMenu(GuyHandleMenu);
  1002.   glutAddSubMenu("Viewing", sub1);
  1003.   glutAddSubMenu("Model", sub2);
  1004.   glutAddMenuEntry("Toggle Axes",    GMENU_AXES);
  1005.   glutAddMenuEntry("Toggle Perspective View", GMENU_PERSP);
  1006.   glutAddMenuEntry("Quit",           GMENU_QUIT);
  1007.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  1008. }
  1009.  
  1010. /***************************************************************/
  1011. /********************* BOTH WINDOWS ****************************/
  1012. /***************************************************************/
  1013.  
  1014. void RedisplayBoth(void)
  1015. {
  1016.   glutSetWindow(GuyWindow);
  1017.   glutPostRedisplay();
  1018.   if (CurveWindowVisible) {
  1019.     glutSetWindow(CurveWindow);
  1020.     glutPostRedisplay();
  1021.   }
  1022. }
  1023.  
  1024. void IncrementStep(void)
  1025. {
  1026.   fStep = fmod(fStep + IncStep, CYCLE_SIZE);
  1027.   Step = (int)fStep;
  1028.   if (agvMoving)
  1029.     agvMove();
  1030.   RedisplayBoth();
  1031. }
  1032.  
  1033. void StopWalking(void)
  1034. {
  1035.   if (Walking) {
  1036.     Walking = 0;
  1037.     agvSetAllowIdle(1);
  1038.   }
  1039. }
  1040.  
  1041. void SetWindowTitles(char *csetname)
  1042. {
  1043.   char windowtitle[MAX_CSETNAMELEN + 20];
  1044.  
  1045.   strcpy(windowtitle, "Rotation Curves: ");
  1046.   strcat(windowtitle, csetname);
  1047.   glutSetWindow(CurveWindow);
  1048.   glutSetWindowTitle(windowtitle);
  1049.  
  1050.   strcpy(windowtitle, "The Guy: ");
  1051.   strcat(windowtitle, csetname);
  1052.   glutSetWindow(GuyWindow);
  1053.   glutSetWindowTitle(windowtitle);
  1054. }
  1055.  
  1056. /***************************************************************/
  1057. /***************************** MAIN ****************************/
  1058. /***************************************************************/
  1059.  
  1060. int main(int argc, char** argv)
  1061. {
  1062.   glutInit(&argc, argv);
  1063.  
  1064.   glutInitWindowSize(512, 512);
  1065.   glutInitWindowPosition(700, 250);
  1066.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  1067.   GuyWindow = glutCreateWindow("The Guy:");
  1068.   agvInit(!Walking);
  1069.   AxesList = glGenLists(1);
  1070.   agvMakeAxesList(AxesList);
  1071.   GuyGLInit();
  1072.   GuyMenuInit();
  1073.   glutDisplayFunc(GuyDisplay);
  1074.   glutReshapeFunc(GuyReshape);
  1075.   glutKeyboardFunc(GuyHandleKeys);
  1076.  
  1077.   glutInitWindowSize(512, 1024);
  1078.   glutInitWindowPosition(100, 0);
  1079.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  1080.   CurveWindow = glutCreateWindow("Rotation Curves:");
  1081.   CurveGLInit();
  1082.   glutDisplayFunc(CurveDisplay);
  1083.   glutReshapeFunc(CurveReshape);
  1084.   glutMouseFunc(CurveHandleButton);
  1085.   glutMotionFunc(CurveHandleMotion);
  1086.   glutKeyboardFunc(CurveHandleKeys);
  1087.   glutVisibilityFunc(CurveVisible);
  1088.  
  1089.   FlatCSet();
  1090.   MakeLists();
  1091.  
  1092.   if (MakeLoadAndSaveMenus() > 0)  /* read first curve if there was one */
  1093.     HandleLoadMenu(0);
  1094.  
  1095.   CurveMenuInit();
  1096.  
  1097.   glutMainLoop();
  1098.   return 0;             /* ANSI C requires main to return int. */
  1099. }
  1100.  
  1101.  
  1102.  
  1103.  
  1104.